package sample;

import sample.Ioliu;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 压缩算法类
 * 实现文件压缩，文件夹压缩，以及文件和文件夹的混合压缩
 *
 * @author ljheee
 */
public class CompactAlgorithm {

    /**
     * 完成的结果文件--输出的压缩文件
     */
    File targetFile;

    public CompactAlgorithm() {
    }

    public CompactAlgorithm(File target) {
        targetFile = target;
        if (targetFile.exists())
            targetFile.delete();
    }

    /**
     * 压缩文件
     *
     * @param srcfile
     */
    public void zipFiles(File srcfile) {
        File outDir = new File(targetFile.getParentFile().getPath() + File.separator + srcfile.getName());
        outDir.mkdirs();
        Arrays.asList(Objects.requireNonNull(srcfile.listFiles()))
                .forEach(file -> {
                    if (file.isFile()) {
                        try {
                            Ioliu.fileCopy(file.getPath(), new File(outDir + File.separator + file.getName()).getPath());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else if (!needZip(file)) {
                        try {
                            Ioliu.copy(file.getPath(), new File(outDir + File.separator + file.getName()).getPath());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    } else {
                        ZipOutputStream out = null;
                        try {
                            String zipFilePath = targetFile.getParentFile().getPath() + File.separator + srcfile.getName() + File.separator + file.getName();
                            out = new ZipOutputStream(new FileOutputStream(zipFilePath));
                            compress(file, out, "");
                            System.out.println(file.getName() + " 压缩完毕");
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            try {
                                if (out != null)
                                    out.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                });

        ZipOutputStream out = null;
        try {
            out = new ZipOutputStream(new FileOutputStream(outDir + ".itz"));
            compress(outDir, out, "");
            System.out.println("压缩完毕");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private boolean needZip(File file) {
        if ("icons".equals(file.getName())
                || "preview".equals(file.getName())
                || "launcher".equals(file.getName())
                || "wallpaper".equals(file.getName())) {
            return false;
        }
        return true;
    }

    /**
     * 压缩文件夹里的文件
     * 起初不知道是文件还是文件夹--- 统一调用该方法
     *
     * @param file
     * @param out
     * @param prefix
     */
    private void compress(File file, ZipOutputStream out, String prefix) throws Exception {
        /* 判断是目录还是文件 */
        if (file.isDirectory()) {
            zipDirectory(file, out, prefix);
        } else {
            zipFile(file, out, prefix);
        }
    }

    /**
     * 压缩单个文件
     *
     * @param srcfile
     */
    public void zipFile(File srcfile, ZipOutputStream out, String basedir) throws Exception {
        FileInputStream in = new FileInputStream(srcfile);
        ZipEntry zipEntry = new ZipEntry(basedir);
        out.putNextEntry(zipEntry);
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        out.closeEntry();
        in.close();
    }

    /**
     * 压缩文件夹
     *
     * @param dir
     * @param out
     * @param basedir
     */
    public void zipDirectory(File dir, ZipOutputStream out, String basedir) throws Exception {
        if (basedir.length() > 0) {
            ZipEntry zipEntry = new ZipEntry(basedir + "/");
            out.putNextEntry(zipEntry);
        }
        basedir = basedir.length() == 0 ? "" : basedir + "/";

        for (File f : dir.listFiles()) {
            compress(f, out, basedir + f.getName());
        }
    }


    //测试
//    public static void main(String[] args) {
//        File f = new File("E:\\第二阶段素材\\白富美密码锁");
//        new CompactAlgorithm(new File("F:", f.getName() + ".itz")).zipFiles(f);
//    }

}